package controller

import (
	"encoding/base64"
	"encoding/json"
	"fmt"
	"github.com/gin-gonic/gin"
	"io/ioutil"
	"myproject/model"
	"myproject/schemas"
	"myproject/utils"
	"net/http"
	"net/url"
	"reflect"
	"regexp"
	"strconv"
	"strings"
)

// 路由总接口
func UserRegister(userPath *gin.RouterGroup) {
	//发送验证码
	userPath.Use().GET("/addUser", addUser)
	//登录
	userPath.Use().POST("/login", login)
	// 获取微博连接
	userPath.Use().GET("/get_weibo", get_weibo)
	// 微博回调
	userPath.Use().GET("/weiboCallback", weiboCallback)
	//三方登录
	userPath.Use().POST("/bin", bindMobile)
	//调百度的文字识别
	userPath.Use().GET("/Diao", Diao)
	//添加数据到开户表
	userPath.Use().POST("/tian", tian)
	//上传图片
	userPath.Use().POST("/fileuUpoad", fileuUpoad)
	//上传首页图片
	userPath.Use().POST("/fileu", fileu)
	//获取首页图片
	userPath.Use().POST("/getHotPicture", getHotPicture)
	//审核
	userPath.Use().GET("/Bankrollback", Bankrollback)
	//获取公告
	userPath.Use().GET("/GetProclamation", GetProclamation)
	//添加公告
	userPath.Use().POST("/AddProclamation", AddProclamation)
}

// 发送验证码------------
func addUser(c *gin.Context) {
	//获取参数
	mobile := c.Query("mobile")
	//真则表达式，验证手机号是否合法
	res := "^1[3-9]{1}\\d{9}$"
	//匹配真则的方法
	result := regexp.MustCompile(res)
	//返回 MatchString 是否匹配
	flag := result.MatchString(mobile)
	if !flag {
		c.JSON(200, gin.H{
			"code": "10001",
			"msg":  "手机号不正确",
		})
	} else {
		//从redis中获取手机号的验证码
		r := utils.GetRedis()
		value := r.Get(mobile)
		//判断验证码是否为空
		if value == "" {
			//随机生成验证码
			code := utils.RandInt(10000, 99999)
			//调用发送短信接口
			utils.SendSms(mobile, code)
			//存入redis

			r.Setex(mobile, 60, code)
			c.JSON(200, gin.H{
				"code": "200",
				"mes":  "发送成功",
				"sms":  code,
			})
		} else {
			c.JSON(200, gin.H{
				"code": "10021",
				"msg":  "不能重复发",
			})
		}
	}
}

type UserLogin struct {
	Mobile string
	Code   string
}

// 登录
func login(c *gin.Context) {
	//获取参数
	user_info := &UserLogin{}
	_ = c.Bind(user_info)
	mobile := "游客" + user_info.Mobile[len(user_info.Mobile)-4:]
	code := user_info.Code
	if user_info.Mobile == "" || user_info.Code == "" {
		c.JSON(200, gin.H{
			"code": "10001",
			"msg":  "账号不能为空",
		})
	}
	//从redis中获取手机号的验证码
	r := utils.GetRedis()
	codes := r.Get(mobile)
	//判断验证码是否一致
	if code != codes {
		c.JSON(404, gin.H{
			"code": "10201",
			"msg":  "验证码错误",
		})
	} else {
		stu := &model.User{
			Name:   mobile,
			Mobile: mobile,
		}
		//加入数据库
		model.DB.Create(stu)
		//生成token返回
		token, _ := utils.ReleaseToken(stu.ID)
		c.JSON(200, gin.H{
			"code":   "200",
			"msg":    "登陆成功",
			"userid": stu.ID,
			"token":  token,
		})
	}
}

// 获取微博 连接
func get_weibo(c *gin.Context) {
	//微博唯一标识
	clientid := "3674019597"
	//回调地址
	reurl := "http://127.0.0.1:8000/user/weiboCallback/"

	returnUrl := "https://api.weibo.com/oauth2/authorize?client_id=" + clientid + "&redirect_uri=" + reurl + "&response_type=code"
	fmt.Println(returnUrl)
	c.JSON(200, gin.H{
		"code": 200,
		"url":  returnUrl,
	})
}

// 微博回调
func weiboCallback(c *gin.Context) {
	//获取code
	code := c.Query("code")
	//组装数据post请求验证=
	// data = {"client_id":'3674019597',"client_secret":"7ae99bc0d54ead29fc8d1b9fabd78587",
	// "grant_type":"authorization_code",
	// 'redirect_uri':'http://127.0.0.1:8000/user/weiboCallback/','code':code}
	geturl := "https://api.weibo.com/oauth2/access_token"
	data := url.Values{}
	data.Add("client_id", "3674019597")
	data.Add("client_secret", "7ae99bc0d54ead29fc8d1b9fabd78587")
	data.Add("grant_type", "authorization_code")
	data.Add("redirect_uri", "http://127.0.0.1:8000/user/weiboCallback/")
	data.Add("code", code)
	res, _ := http.PostForm(geturl, data)

	//成功 uid ,token
	body, _ := ioutil.ReadAll(res.Body)

	var v interface{}
	json.Unmarshal([]byte(string(body)), &v)
	resultmes := v.(map[string]interface{})
	actoken, flag := resultmes["access_token"]
	if flag {
		fmt.Println("actoken", actoken)
	}
	uid, uflag := resultmes["uid"]
	if uflag {
		fmt.Println("uid", uid)
	}

	conn := model.GetDb()
	var sflogin model.SfLogin
	conn.First(&sflogin, "Userid=?", uid)
	//如果存在用userid生成token，redirect到vue页面

	fmt.Println(reflect.TypeOf(actoken))
	fmt.Println(reflect.TypeOf(uid))
	fmt.Println(strconv.Itoa(int(sflogin.ID)), ".....................................................")
	// 7796037166
	fmt.Println(sflogin.ID, "............................===.........................")

	if sflogin.ID != 0 {
		//生成token
		token, _ := utils.ReleaseToken(sflogin.ID)
		c.Redirect(http.StatusMovedPermanently, "http://localhost:8080/home?token="+token+"&userid="+strconv.Itoa(int(sflogin.ID)))
	} else {

		fmt.Println(sflogin.ID, "............................===.........................")
		c.Redirect(http.StatusMovedPermanently, "http://localhost:8080/bindMobile?token="+fmt.Sprint(actoken)+"&uid="+fmt.Sprint(uid))
	}
}

// 三方登录
func bindMobile(c *gin.Context) {
	//结构体的类型都是字符串
	createUser := &schemas.CreateUser{}
	_ = c.Bind(createUser)
	token := createUser.Token
	uid := createUser.Uid
	mobile := createUser.Mobile

	fmt.Println(">>>>>>>>>>>>>>>>>>>>>>", createUser)

	//查询用户表中的此手机号是否存在
	var user model.User
	conn := model.GetDb()
	conn.First(&user, "mobile=?", mobile)

	//已经存在找出Userid,写入三方登录表
	var ctokenuserid uint = 0

	//判断用户id是否为0
	if user.ID != 0 {
		//生成token返回
		ctokenuserid = user.ID
	} else {
		//不存在先写用户表，生成一个userid，再写三方登录表
		createUser := &model.User{
			Name:   mobile,
			Mobile: mobile,
		}
		//向用户表添加数据
		conn.Create(createUser)
		ctokenuserid = createUser.ID
	}

	ctoken, _ := utils.ReleaseToken(ctokenuserid)
	//写入三方登录表
	sflogin := &model.SfLogin{
		Uid:      ctokenuserid,
		Token:    token,
		PlatForm: "weibo",
		Userid:   uid,
	}
	//向三方登录表添加数据
	conn.Create(sflogin)
	c.JSON(200, gin.H{
		"code":   200,
		"token":  ctoken,
		"userid": ctokenuserid,
	})
}

// 获取百度云的token
func Access() string {

	var host = "https://aip.baidubce.com/oauth/2.0/token"
	var param = map[string]string{
		"grant_type":    "client_credentials",
		"client_id":     "DxVwuVTevPNpT1lEPDGt0DAP",
		"client_secret": "C38aMNjRZiTAXsEujo2hABEX838ru5rE",
	}

	uri, err := url.Parse(host)
	if err != nil {
		fmt.Println(err)
	}
	query := uri.Query()
	for k, v := range param {
		query.Set(k, v)
	}
	uri.RawQuery = query.Encode()

	response, err := http.Get(uri.String())
	if err != nil {
		fmt.Println(err)
	}
	result, err := ioutil.ReadAll(response.Body)
	if err != nil {
		fmt.Println(err)
	}

	var v interface{}
	//把string转成接口
	json.Unmarshal([]byte(string(result)), &v)
	Accse := v.(map[string]interface{})
	wordslist := Accse["access_token"].(string)
	return wordslist

}

// 调百度的文字识别
func Diao(c *gin.Context) {
	img := c.Query("img")
	var host = "https://aip.baidubce.com/rest/2.0/ocr/v1/general_basic"
	var accessToken = Access()

	uri, err := url.Parse(host)
	if err != nil {
		fmt.Println(err)
	}
	query := uri.Query()
	query.Set("access_token", accessToken)
	uri.RawQuery = query.Encode()

	filebytes, err := ioutil.ReadFile(img)
	if err != nil {
		fmt.Println(err)
	}

	image := base64.StdEncoding.EncodeToString(filebytes)
	sendBody := http.Request{}
	sendBody.ParseForm()
	sendBody.Form.Add("image", image)
	sendData := sendBody.Form.Encode()

	client := &http.Client{}
	request, err := http.NewRequest("POST", uri.String(), strings.NewReader(sendData))
	if err != nil {
		fmt.Println(err)
	}
	request.Header.Set("Content-Type", "application/x-www-form-urlencoded")

	response, err := client.Do(request)
	defer response.Body.Close()
	result, err := ioutil.ReadAll(response.Body)
	if err != nil {
		fmt.Println(err)
	}

	//定一个接口
	var v interface{}
	//把string转成接口
	json.Unmarshal([]byte(string(result)), &v)
	mesdict := v.(map[string]interface{})
	wordslist := mesdict["words_result"].([]interface{})

	var cardlist []string
	for _, vv := range wordslist {
		words := vv.(map[string]interface{})
		for _, vser := range words {
			cardlist = append(cardlist, vser.(string))
		}
	}
	c.JSON(200, gin.H{
		"code": "200",
		"name": cardlist[0],
		"card": cardlist[1],
	})
}

type kai struct {
	Name       string
	CardNumber string
	BankCode   string
	Mobile     string
}

// 添加到开户表
func tian(c *gin.Context) {
	kaihu := &kai{}
	_ = c.Bind(kaihu)

	add := &model.OpenBank{
		Name:       kaihu.Name,
		BankCode:   kaihu.BankCode,
		CardNumber: kaihu.CardNumber,
		Mobile:     kaihu.Mobile,
	}

	model.DB.Create(add)

	var ID int

	sql := "select ID from open_banks where card_number=?"
	model.DB.Raw(sql, add.CardNumber).Scan(&ID)

	r := utils.RedisPool
	r.ListAdd("openuser1", ID)

	c.JSON(200, gin.H{
		"code": "200",
		"mes":  "已经提交，等待审核",
	})
}

// 文件上传
func fileuUpoad(c *gin.Context) {
	f, err := c.FormFile("file")
	//index := f.Filename
	//fmt.Println(index)
	if err != nil {
		c.JSON(200, gin.H{
			"code": "10031",
			"msg":  "获取文件失败",
		})
		return
	}
	indesc := "img/" + f.Filename
	if err := c.SaveUploadedFile(f, "img/"+f.Filename); err != nil {
		c.JSON(200, gin.H{
			"code": "10021",
			"msg":  "保存文件失败",
		})
	}
	c.JSON(200, gin.H{
		"code": "200",
		"msg":  "文件上传成功",
		"inde": indesc,
	})
}

type fileun struct {
	Image_Address string
	Jump_address  string
	Name          string
}

// 上传首页图片
func fileu(c *gin.Context) {
	file_un := &fileun{}
	_ = c.Bind(file_un)

	stu := &model.Picture{
		Image_Address: file_un.Image_Address,
		Jump_address:  file_un.Jump_address,
		News:          file_un.Name,
	}
	//加入数据库
	model.DB.Create(stu)
	c.JSON(200, gin.H{
		"code": "200",
		"msg":  "提交成功",
	})

}

// 获取首页图片
func getHotPicture(c *gin.Context) {
	r := utils.RedisPool
	hotp := r.Get("getpicture")
	if hotp != "" {
		fmt.Printf("上面")

		var aa interface{}
		json.Unmarshal([]byte(hotp), &aa)
		hotpicture := aa.([]interface{})

		c.JSON(200, gin.H{
			"code": 200,
			"msg":  "热门图片获取成功",
			"data": hotpicture,
		})
	} else {

		flag := r.Setex("getpictureuser", 100, "1")
		if flag {
			var hotpicture []schemas.HotPicture
			sql := "select * from hot_pictures order by id desc limit 0,3"
			model.DB.Raw(sql).Scan(&hotpicture)
			ulist, _ := json.Marshal(hotpicture)

			r.Setex("getpicture", 1000, ulist)
			r.StrDel("getpictureuser")

			c.JSON(200, gin.H{
				"code": 200,
				"msg":  "热门图片获取成功",
				"data": hotpicture,
			})
		}

	}

}

// 审核
func Bankrollback(c *gin.Context) {
	id := c.Query("id")
	status := c.Query("status")
	sql := "update open_banks set status=? where id=?"
	err := model.DB.Exec(sql, status, id)
	fmt.Println(err, sql)
	if err.Error != nil {
		fmt.Println(err.Error)
		return
	}
	c.JSON(200, gin.H{
		"code": 200,
		"msg":  "审核完成",
	})
}

// 添加公告
func AddProclamation(c *gin.Context) {
	pro := schemas.Proclamation{}
	_ = c.Bind(&pro)
	if pro.Content == "" {
		c.JSON(200, gin.H{
			"code": 10021,
			"msg":  "不能为空",
		})
		return
	}
	sql := "INSERT INTO proclamations(Content) values (?)"
	model.DB.Exec(sql, pro.Content)
	c.JSON(200, gin.H{
		"code": 200,
		"msg":  "添加成功",
	})
}

// 获取公告
func GetProclamation(c *gin.Context) {

	r := utils.RedisPool
	pro := r.Get("getProclamation")
	if pro != "" {
		fmt.Printf("上面")

		var aa interface{}
		json.Unmarshal([]byte(pro), &aa)
		proclamation := aa.([]interface{})

		c.JSON(200, gin.H{
			"code": 200,
			"msg":  "公告获取成功",
			"data": proclamation,
		})
	} else {

		flag := r.Setex("getproclamationuser", 100, "1")
		if flag {
			pro := model.Proclamation{}
			_ = c.Bind(pro)
			sql := "SELECT * from proclamations order by id desc limit 0,5"
			var prodata []schemas.ProData
			model.DB.Raw(sql).Scan(&prodata)

			ulist, _ := json.Marshal(prodata)

			r.Setex("getProclamation", 1000, ulist)
			r.StrDel("getproclamationuser")

			c.JSON(200, gin.H{
				"code": 200,
				"msg":  "公告获取成功",
				"data": prodata,
			})
		}

	}

}
